#ifndef __SERVER_H__
#define __SERVER_H__

/*!
 * \file Server.h
 * \brief Contient le necessaire a la creation d'un serveur Agora
 */

#include <time.h>
#include <list>
#include <map>
#include "Client.h"
#include "Host.h"
#include "ThreadPool.h"
#include "Mutex.h"
#include "AdminIHost.h"
#include "AdminInterpreter.h"
//#include "AdminIChannelManager.h";

/*! \class Server
   * \brief Classe decrivant un serveur
   *
   *  Classe permettant d'implementer un serveur Agora et gerer les connections clientes
   */
namespace AgoraServer
{

class Server
{
public:
	/*!
     *  \brief Constructeur
     *
     *  Constructeur de la classe Server
     *
     */
	Server();
	/*!
	*	\brief Lance un serveur
	*	
	*	Methode servant a initialiser et lancer un serveur Agora
	*
	*	\param port : Port d'ecoute du serveur sur lequel les clients peuvent se connecter,
	*	\param address : Adresse IP de l'interface reseau du serveur qui sera utilisee
	*	\return Si la methode echoue un code d'erreur est retourne sinon 0 est renvoye
	*/
	unsigned int		Start(unsigned short int soundPort, unsigned short int admTxtPort, const std::string& address);
	/*!
	*	\brief Accesseur de l'empacteur Agora
	*	
	*	Accesseur de l'empacteur associe au serveur et utilise dans le protocole d'echange de donnees entre les clients
	*
	*	\return Retourne un pointeur sur l'empacteur Agora
	*/
	IEmpacter*			GetEmpacter();
	/*!
	*	\brief Accesseur de la liste des clients
	*	
	*	Accesseur de la liste des clients actuellement connectes au serveur
	*
	*	\return Retourne un pointeur sur la liste des clients connectes au serveur
	*/
	std::list<Client*>* GetClient();
	/*!
	*	\brief Accesseur du mutex lie au parcours de la liste de clients
	*	
	*	Accesseur du mutex lie au parcours de la liste de clients
	*
	*	\return	Retourne un pointeur sur le mutex
	*/
	IMutex*				GetMutexClientListBrowse();
	/*!
	*	\brief Accesseur du mutex lie a la modification de la liste de clients
	*	
	*	Accesseur du mutex lie a la modification de la liste de clients
	*
	*	\return Retourne un pointeur sur le mutex
	*/
	IMutex*				GetMutexClientListModification();
	/*!
	*	\brief Compteur d'acces a la liste de clients
	*	
	*	Doit etre appele lors de chaque acces a la liste de clients, que ce soit pour un parcours ou une modification de cette liste
	*
	*	\param need : Valeur booleene, vrai indique que l'on ajoute un marqueur signifiant que l'on accede a la liste des clients, et faux que l'on y accede plus
	*/
	void				AccesClientList(bool need);
	/*!
	*	\brief Renseigne sur l'acces a la liste des clients
	*	
	*	Renseigne sur l'acces a la liste des clients, si vrai est retourne, la liste des clients est actuellement accedee
	*
	*	\return Valeur booleene
	*/
	bool				ClientListIsAccessed();
	
	unsigned int		_octIn;	/*!< Nombre d'octets entrant*/
	unsigned int		_octOut;	/*!< Nombre d'octects sortant*/

private:

	static void	ForcedDisconnection(AgoraAdmin::IUser *user, void *data);
 /**
 * \struct info_select
 * \brief Structure d'information reliant un server et un client.
 *
 * info_select est une structure contenant un pointeur sur un serveur et un pointeur sur un client.
 * Cette structure est utilisee lors du passage de parametre a la methode Server::SelectReceiveTxtAdm
 */
	struct info_select
	{
		Server* server;	/*!< pointeur sur un objet Server*/
		Client* client;	/*!< pointeur sur un objet Client*/
	};

 /**
 * \struct info_selectSound
 * \brief Structure d'information reliant un server et une connection.
 *
 * info_selectSound est une structure contenant un pointeur sur un serveur et un pointeur sur une connection.
 * Cette structure est utilisee lors du passage de parametre a la methode Server::SelectReceiveSound
 */
	struct info_selectSound
	{
		Server* server;	/*!< pointeur sur un objet Server*/
		AgoraCore::Connection *connection;	/*!< pointeur sur un objet Connection*/
	};


	/*!
	*	\brief Accepte les connections entrantes cote Adm
	*	
	*	Permet d'accepter aux connections entrantes des clients et lance un thread lie a chacun de ces clients pour identifier l'utilisateur puis traiter les donnees admin et textes qu'ils envoient
	*
	*	\param server : pointeur de type Server
	*/
	static void		AcceptClientTxtAdm(void * server);

	/*!
	*	\brief Accepte les connections entrantes cote son
	*	
	*	Permet d'accepter aux connections entrantes des clients et lance un thread lie a chacun de ces clients pour traiter les donnees sons qu'ils envoient
	*
	*	\param server : pointeur de type Server
	*/
	static void		AcceptClientSound(void *server);

	/*!
	*	\brief Verification de l'identite du client
	*	
	*	Test le mot de passe et le login de client et lui attribue un id
	*
	*	\param server : Pointeur sur une structure de type info_select
	*/
	static bool	AuthClient(info_select* inf);

	/*!
	*	\brief Relais clients
	*	
	*	Lit des donnees sons sur la connection d'un client et les retransmets aux autres clients
	*
	*	\param data : Pointeur sur une structure de type info_select
	*/
	static void			SelectReceiveSound(void* data);

	/*!
	*	\brief Relais clients
	*	
	*	Lit des donnees admin et texte sur la connection d'un client et les retransmets aux autres clients
	*
	*	\param data : Pointeur sur une structure de type info_selectSound
	*/
	static void			SelectReceiveTxtAdm(void* data);

	/*!
	*	\brief Supprime un client
	*	
	*	Supprime un client de la liste de clients connectes au serveur
	*
	*	\param client : Pointeur sur un objet Client
	*/
	void				RemoveClient(Client* client);
	bool				IsClientConnected(Client* client);
	/*!
	*	\brief Ajoute un client
	*	
	*	Ajoute un client a la liste de clients du serveur
	*
	*	\param client : Pointeur sur un objet Client
	*/
	void				AddClient(Client* client);

	void				SendAdmReturnInfo(Client* client, AgoraAdmin::AdminInterpreter::ReturnInfo* ret);

	AgoraAdmin::AdminInterpreter*	GetAdminInterpreter();
	
	IMutex*				_mtxClientListModification;	/*!< mutex de modification de la liste de clients*/
	IMutex*				_mtxClientListBrowse;	/*!< mutex de parcours de la liste de clients*/
	unsigned int		_clientListNbAcces;	/*!< nombre d'acces a la liste de clients*/
	AgoraCore::Host*		_cnt;	/*!< pointeur sur l'objet connection hote gerant le son*/
	AgoraCore::Host*		_cntTxtAdm; /*!< pointeur sur l'objet connection hote gerant les messages d'admin et les messages textes*/
	IEmpacter*			_emp;	/*!< pointeur sur l'empacteur Agora*/

	// TODO MAP
	std::list<Client*>	_clientList;	/*!< liste de clients connectes au serveur*/
	// TODO
	std::map<AgoraAdmin::IUser*, Client*>	_mapIUserClient; // permet de retrouver la connection adm d'un user pour lui envoyer des infos
	std::map<Client*, AgoraAdmin::IUser*>	_mapClientIUser; // permet l'interaction d'un client sur la partie adm

	AgoraAdmin::IHost*						_adminServer;
	AgoraAdmin::AdminInterpreter*			_interpreter;

	IMutex*								_mtxAdminAcces;
};

}

#endif //__SERVER_H__
